<template>
  <v-table
    :columns="tableColumns"
    :dataSource="dataSource"
    :loading="loading"
    :total="total"
    @select-all="handleSelectAll"
    @select="handleSelect"
    ref="table"
    showOverflowTooltip
    v-bind="bindProps"
    v-on="bindListeners"
  >
    <template slot="toolbar">
      <el-form inline size="small" :model="query" ref="query" class="flex flex-wrap">
        <template v-if="queryTypes.goods">
          <el-form-item prop="goodsName">
            <el-input placeholder="请输入商品名称" v-model.trim="query.goodsName" />
          </el-form-item>
          <el-form-item prop="goodsState">
            <el-select v-model="query.goodsState" placeholder="请选择商品状态">
              <el-option
                v-for="(it, i) in onlineStatus"
                :key="i"
                :label="it.label"
                :value="it.value"
              ></el-option>
            </el-select>
          </el-form-item>
        </template>
        <template v-else-if="queryTypes.category">
          <el-form-item prop="classifyName">
            <el-input placeholder="请输入分类名称" v-model.trim="query.classifyName" />
          </el-form-item>
        </template>
        <template v-else-if="queryTypes.coupon">
          <el-form-item prop="couponName">
            <el-input placeholder="请输入优惠卷名称" v-model.trim="query.couponName" />
          </el-form-item>
        </template>
        <el-form-item>
          <el-button type="success" @click="handleSearch">查询</el-button>
          <el-button type="warning" @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </template>
  </v-table>
</template>

<script>
/* model
------------------------------------------------------------------------------ */
import { bannerResourceTypeEnum, onlineStatusEnum } from '@/core/enum'
import {
  discountCouponTypes,
  discountCouponValidity
} from '@/views/product-operation/discount-coupon/model'
/* api
------------------------------------------------------------------------------ */
import {
  getFreshGoodsList,
  getDiscountCouponList,
  getMaintenanceGoodsList,
  getFreshCategoryList,
  getMaintenanceCategoryList
} from '@/api'

/* components
------------------------------------------------------------------------------ */
import { Query } from '@/mixins'

export default {
  mixins: [Query('query')],
  props: {
    singlePick: Boolean,
    crossPick: Boolean,
    type: [String, Number],
    lastPicked: {
      type: Array,
      default () {
        return []
      }
    }
  },
  data () {
    return {
      internals: {},
      primaryKey: '',
      labelKey: '',
      loading: false,
      dataSource: [],
      total: 0,
      records: [],
      query: {
        pageSize: 5,
        goodsName: '',
        classifyName: '',
        goodsState: '',
        couponName: ''
      },
      queryTypes: {
        goods: false,
        category: false,
        coupon: false
      },
      crossPickMap: {},
      crossRecords: [],
      tableColumns: [],
      columns: [
        { type: 'selection' },
        { prop: 'goodsName', label: '名称' },
        { prop: 'goodsSummary', label: '简介' },
        {
          prop: 'goodsPriceOriginal',
          label: '原价'
        },
        {
          prop: 'goodsPriceDiscount',
          label: '折扣价'
        },
        {
          prop: 'goodsSalesVolume',
          label: '销量'
        },
        {
          prop: 'goodsPick',
          label: '推荐',
          formatter: (row) => <span>{row['goodsPick'] ? '是' : '否'}</span>
        },
        {
          prop: 'goodsStateValue',
          label: '状态'
        },
        { prop: 'goodsSupplierName', label: '所属供应商' }
      ],
      cateColumns: [
        { type: 'selection' },
        { prop: 'classifyName', label: '分类名称' },
        { prop: 'classifySummary', label: '分类简介' },
        {
          prop: 'classifyIcon',
          label: '分类icon',
          formatter: (row) => {
            const imgSrc = this.$V.staticBaseURL + row['classifyIcon']
            return (
              <el-image
                class="row-img"
                src={imgSrc}
                preview-src-list={[imgSrc]}
              ></el-image>
            )
          }
        },
        {
          prop: 'classifyImage',
          label: '分类图片',
          formatter: (row) => {
            const imgSrc = this.$V.staticBaseURL + row['classifyImage']
            return (
              <el-image
                class="row-img"
                src={imgSrc}
                preview-src-list={[imgSrc]}
              ></el-image>
            )
          }
        }
      ],
      couponColumns: [
        { type: 'selection' },
        { prop: 'couponName', label: '名称' },
        {
          prop: 'couponApplicableScopeValue',
          label: '适用范围'
        },
        {
          prop: 'couponTypeValue',
          label: '优惠卷类型'
        },
        {
          prop: 'couponType',
          label: '优惠内容',
          formatter: (row) => {
            const text =
              row.couponType === discountCouponTypes[0].value
                ? `满 ${row['couponBaseAmount']} 减 ${row['couponReducedAmount']}`
                : `满 ${row['couponBaseAmount']} 打 ${row['couponDiscount']} 折`
            return <span class="striking">{text}</span>
          }
        },
        {
          prop: 'couponValidityTermTypeValue',
          label: '有效类型'
        },
        {
          prop: 'couponValidityTermType',
          label: '有效期',
          formatter: (row) => {
            const text =
              row.couponValidityTermType === discountCouponValidity[0].value
                ? `${row['couponValidityTermStart']} - ${row['couponValidityTermEnd']}`
                : `${row['couponValidityTerm']}天`
            return <span class="striking">{text}</span>
          }
        },
        {
          prop: 'couponStateValue',
          label: '状态'
        },
        {
          prop: 'couponCreateTime',
          label: '创建时间',
          width: this.$V.cellSize.date,
          formatter: (row) => this.$formatTime(row['couponCreateTime'])
        },
        { prop: 'couponCreateUserName', label: '创建人' },
        {
          prop: 'couponUpdateTime',
          label: '修改时间',
          width: this.$V.cellSize.date,
          formatter: (row) => this.$formatTime(row['couponUpdateTime'])
        },
        { prop: 'couponUpdateUserName', label: '修改人' }
      ]
    }
  },

  computed: {
    onlineStatus () {
      return this.$mapEnumToSelect(onlineStatusEnum)
    }
  },

  methods: {
    // -------------------------------------------- 处理单选 开始 --------------------------------------------
    handleSelect (selection, row) {
      const { primaryKey } = this
      if (!this.singlePick) {
        return
      }
      let index = this.dataSource.findIndex(
        (it) => it[primaryKey] === row[primaryKey]
      )

      this.$refs.table.clearSelection()

      if (index !== this.currentIndex) {
        this.currentIndex = index
        this.$nextTick(() => {
          this.currentIndex = this.dataSource.findIndex(
            (it) => it[primaryKey] === row[primaryKey]
          )
          this.$refs.table
            .getElTable()
            .toggleRowSelection(this.dataSource[this.currentIndex])
        })
      } else {
        this.currentIndex = -1
      }
    },
    handleSelectAll () {
      if (!this.singlePick) {
        return
      }
      this.$refs.table.clearSelection()
      this.currentIndex = -1
    },
    // -------------------------------------------- 处理单选 结束 --------------------------------------------

    /* Requests
    ------------------------------------------------------------------------ */
    getFreshGoodsList (fn) {
      return this.Catch(getFreshGoodsList, {
        onOk (res) {
          this.dataSource = res.data.data
          this.total = res.data.total
          this.onRequestOk(res.data.data)
        }
      })('loading', (fn || this.$noop)(this.query))
    },

    getDiscountCouponList (fn) {
      return this.Catch(getDiscountCouponList, {
        onOk (res) {
          this.dataSource = res.data.data
          this.total = res.data.total
          this.onRequestOk(res.data.data)
        }
      })('loading', (fn || this.$noop)(this.query))
    },

    getMaintenanceGoodsList (fn) {
      return this.Catch(getMaintenanceGoodsList, {
        onOk (res) {
          this.dataSource = res.data.data
          this.total = res.data.total
          this.onRequestOk(res.data.data)
        }
      })('loading', (fn || this.$noop)(this.query))
    },

    getFreshCategoryList (fn) {
      return this.Catch(getFreshCategoryList, {
        onOk (res) {
          this.dataSource = res.data.data
          this.total = res.data.total
          this.onRequestOk(res.data.data)
        }
      })('loading', (fn || this.$noop)(this.query))
    },
    getMaintenanceCategoryList (fn) {
      return this.Catch(getMaintenanceCategoryList, {
        onOk (res) {
          this.dataSource = res.data.data
          this.total = res.data.total
          this.onRequestOk(res.data.data)
        }
      })('loading', (fn || this.$noop)(this.query))
    },

    /* Table
    ------------------------------------------------------------------------ */
    beforePageNumChange () {
      this.isChangingPageNum = true
    },
    afterPageNumChange () {
      this.isChangingPageNum = false
    },
    assertSelection () {
      let checkArray = this.singlePick ? this.records : this.crossRecords
      if (checkArray.length === 0) {
        throw new Error(this.$t('at least one record must be selected'))
      }
    },

    handleSelectionChange (rows) {
      if (!this.crossPick) {
        this.records = rows
        return
      }

      if (this.isChangingPageNum) {
        return
      }

      const pageNum = this.getPageNum()
      const { primaryKey, labelKey } = this
      const willBeDeletedOfThisPage = this.$differenceBy(this.crossPickMap[pageNum], rows, this.primaryKey)

      this.crossPickMap[pageNum] = rows.filter(Boolean).map(
        (it) => {
          return {
            [primaryKey]: it[primaryKey],
            [labelKey]: it[labelKey]
          }
        }
      )

      let crossRecords = Object.keys(this.crossPickMap).reduce(
        (prev, curr) => {
          return prev.concat(this.crossPickMap[curr])
        },
        []
      ).concat(this.internals.lastPicked)

      this.crossRecords = this.$differenceBy(crossRecords, willBeDeletedOfThisPage, this.primaryKey)
    },

    /* Expose methods
    ------------------------------------------------------------------------ */
    getSelection () {
      return this.crossPick ? this.crossRecords : this.records
    },

    /* Private methods
    ------------------------------------------------------------------------ */
    getPageNum () {
      return this.query.pageNum
    },
    eq (x, y) { return x[this.primaryKey] === y[this.primaryKey] },
    contain (x, y) { return !!x.find(i => this.eq(i, y)) },

    onRequestOk (rows) {
      const pageNum = this.getPageNum()

      if (!this.crossPickMap[pageNum]) {
        this.$set(this.crossPickMap, pageNum, [])
      }

      this.$nextTick(() => {
        if (!this.internals.lastPicked) {
          this.$set(this.internals, 'lastPicked', this.lastPicked)
        }

        let filteredLastPicked = this.internals.lastPicked.filter(item => {
          if (this.contain(rows, item)) {
            !this.contain(this.crossPickMap[pageNum], item) && this.crossPickMap[pageNum].push(item)
            return false
          }
          return true
        })
        this.internals.lastPicked = filteredLastPicked
        const targets = this.crossPickMap[pageNum]

        const { primaryKey } = this
        rows.forEach((row, index) => {
          let checked =
            targets.findIndex((it) => it[primaryKey] === row[primaryKey]) > -1
          this.$refs.table
            .getElTable()
            .toggleRowSelection(rows[index], checked)
        })
      })
    },

    setRequestAndQueryParams () {
      let request
      switch (this.type) {
        case bannerResourceTypeEnum.fresh:
          request = this.getFreshGoodsList
          this.tableColumns = this.columns
          this.primaryKey = 'goodsId'
          this.labelKey = 'goodsName'
          this.queryTypes = {
            goods: true,
            category: false,
            coupon: false
          }
          break
        case bannerResourceTypeEnum.maintenance:
          request = this.getMaintenanceGoodsList
          this.tableColumns = this.columns
          this.primaryKey = 'goodsId'
          this.labelKey = 'goodsName'
          this.queryTypes = {
            goods: true,
            category: false,
            coupon: false
          }
          break
        case bannerResourceTypeEnum.freshCategory:
          request = this.getFreshCategoryList
          this.tableColumns = this.cateColumns
          this.primaryKey = 'classifyId'
          this.labelKey = 'classifyName'
          this.queryTypes = {
            goods: false,
            category: true,
            coupon: false
          }
          break
        case bannerResourceTypeEnum.maintenanceCategory:
          request = this.getMaintenanceGoodsList
          this.tableColumns = this.columns
          this.primaryKey = 'goodsId'
          this.labelKey = 'goodsName'
          this.queryTypes = {
            goods: false,
            category: true,
            coupon: false
          }
          break
        case bannerResourceTypeEnum.coupon:
          request = this.getDiscountCouponList
          this.tableColumns = this.couponColumns
          this.primaryKey = 'couponId'
          this.labelKey = 'couponName'
          this.queryTypes = {
            goods: false,
            category: false,
            coupon: true
          }
          break
      }
      if (request) {
        request()
        this.inject(request)
      }
    }
  },

  created () {
    this.setRequestAndQueryParams()
  }
}
</script>
